package com.spark.common.ext

import android.annotation.SuppressLint
import android.app.Activity
import android.support.design.widget.TabLayout
import android.support.v4.app.Fragment
import android.util.TypedValue
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Toast
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.spark.common.widget.Alert
import com.tencent.bugly.crashreport.CrashReport
import com.yanzhenjie.permission.AndPermission
import es.dmoral.toasty.Toasty
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import jp.wasabeef.glide.transformations.RoundedCornersTransformation
import java.util.concurrent.TimeUnit

/**
 * Disposable 判空 取消执行
 */
fun Disposable?.cancel() {
    if (this == null) return
    if (!isDisposed)
        dispose()
}

/**
 * RxJava IO UI 线程切换，执行异步操作/耗时复杂操作
 */
fun <T> Observable<T>.wrapIO(): Observable<T> {
    return subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.io())
}

fun <T> Single<T>.wrapIO(): Single<T> {
    return subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.io())
}

fun <T> Observable<T>.wrapCompute(): Observable<T> {
    return subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.computation())
}

fun <T> Single<T>.wrapCompute(): Single<T> {
    return subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.computation())

}

/**
 * 将任意函数使用 dsl 方式部署
 */
fun <T> T.dsl(block: T.() -> Unit): T {
    block(this)
    return this
}

@SuppressLint("CheckResult")
fun View.singleClickListener(init: () -> Unit?) {
    Observable
            .create<Any> { emitter ->
                this.setOnClickListener {
                    emitter.onNext(1)
                    emitter.onComplete()
                }

                emitter.setCancellable {
                    this.setOnClickListener(null)
                }
            }.takeLast(800, TimeUnit.SECONDS)
            .wrapIO()
            .subscribe { init() }
}


/**
 * 请求权限
 */
fun Activity.requestPermission(permissionNames: Array<String>,
                               rational: String = "授予这些权限App才能正常运行哦",
                               reason: String = "是否前往设置页面手动授予这些权限",
                               listener: OnRequestPermissionListener?) {
    AndPermission.with(this)
            .permission(permissionNames)
            .rationale { _, _, executor ->
                Alert.Builder(this, rational)
                        .affirm("授予") { d, i ->
                            d.dismiss()
                            executor.execute()
                        }
                        .cancel("拒绝") { d, i ->
                            executor.cancel()
                            d.dismiss()
                        }
                        .create()
                        .show()
            }
            .onGranted {
                listener?.onReturn(true)
            }
            .onDenied {
                if (!AndPermission.hasAlwaysDeniedPermission(this, permissionNames.toMutableList())) {
                    val settingService = AndPermission.permissionSetting(this)
                    Alert.Builder(this@requestPermission, reason)
                            .affirm("前往") { d, i ->
                                d.dismiss()
                                settingService.execute()
                            }
                            .cancel("拒绝") { d, i ->
                                d.dismiss()
                                listener?.onReturn(false)
                                settingService.cancel()
                            }
                            .create()
                            .show()
                } else {
                    listener?.onReturn(false)
                }
            }
            .start()
}

/**
 * 权限请求回调
 */
interface OnRequestPermissionListener {
    /**
     * @isGranted(Boolean) 是否获得授权
     */
    fun onReturn(isGranted: Boolean)
}


/**
 * 从服务器获取图片
 */
fun ImageView.server(url: String) {
    Glide.with(this.context)
            .load(url)
            .into(this)
}

/**
 * 获取本地图片
 */
fun ImageView.local(uri: String) {
    Glide.with(this.context)
            .load(uri)
            .into(this)
}

/**
 * 为 glide 添加圆角
 */
fun <T> T.roundCorner(placeholder: Int, corner: Int = 0, margin: Int = 0): RequestOptions {
    return RequestOptions()
            .placeholder(placeholder)
            .error(placeholder)
            .transform(RoundedCornersTransformation(corner, margin))
}

/**
 * Bugly 上报异常
 */
fun <T> T.report(t: Throwable) {
    CrashReport.postCatchedException(t)
}


fun Activity.error(msg: String) {
    Toasty.error(this, msg, Toast.LENGTH_SHORT, false).show()
}

fun Activity.success(msg: String) {
    Toasty.success(this, msg, Toast.LENGTH_SHORT, false).show()
}

fun Activity.alert(msg: String) {
    Toasty.warning(this, msg, Toast.LENGTH_SHORT, false).show()
}

fun Activity.info(msg: String) {
    Toasty.info(this, msg, Toast.LENGTH_SHORT, false).show()
}

fun Fragment.error(msg: String) {
    activity?.apply { Toasty.error(this, msg, Toast.LENGTH_SHORT, false).show() }
}

fun Fragment.success(msg: String) {
    activity?.apply { Toasty.success(this, msg, Toast.LENGTH_SHORT, false).show() }
}

fun Fragment.alert(msg: String) {
    activity?.apply { Toasty.warning(this, msg, Toast.LENGTH_SHORT, false).show() }
}

fun Fragment.info(msg: String) {
    activity?.apply { Toasty.info(this, msg, Toast.LENGTH_SHORT, false).show() }
}

/**
 * 设置 indicator 左右宽度
 */
fun TabLayout.setIndicatorPadding(left: Float, right: Float) {
    try {
        val tabstrip = this.javaClass.getDeclaredField("mTabStrip")
        tabstrip.isAccessible = true
        val lltab = tabstrip.get(this) as LinearLayout
        val dp_left = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, left, resources.displayMetrics)
        val dp_right = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, right, resources.displayMetrics)
        for (i in 0..lltab.childCount) {
            val child = lltab.getChildAt(i)
            child.setPadding(0, 0, 0, 0)
            val params = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1f)
            params.leftMargin = dp_left.toInt()
            params.rightMargin = dp_right.toInt()
            child.layoutParams = params
            child.invalidate()
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}